#!/usr/bin/env python3

import gt
import os
import sys
import vt
import random

def createCanvas(r, c):
    """
    画布创建
    """
    canvas = list(range(r))
    for x in canvas:
        canvas[x] = list(range(c))
    return canvas

def initCanvas(canvas, row, col):
    """
    画布初始化
    """
    for r in range(row):
        for c in range(col):
            if r == 0 or c == 0 or r == row - 1 or c == col - 1:
                canvas[r][c] = '#'
            else:
                canvas[r][c] = ' '

    return canvas

def showCanvas(ball):
    """
    刷新画布
    """
    canvas = ball['canvas']

    vt.goto(back=False)
    ch = [x['ch'] for x in ball['balls']]
    color = [x['color'] for x in ball['balls']]

    for r in range(ball['row']):
        for c in range(ball['col']):
            point = canvas[r][c]
            if point in ch:
                vt.color(' ', vt.DEFAULT, color[ch.index(point)], back=False)
            else:
                print(point, end='')
        print()

def draw(canvas, row, col, ball):
    """
    在画布上作画,画一个球
    """
    x = ball['x']
    y = ball['y']
    r = ball['r']
    for i in range(y, y + r):
        for j in range(x, x + r):
            if i > row - 1 or j > col - 1 or i < 0 or j < 0:
                continue
            canvas[i][j] = ball['ch']

def draws(ball):
    """
    画所有球
    """
    for i in range(ball['num']):
        draw(ball['canvas'], ball['row'], ball['col'], ball['balls'][i])

def initBallDict(r=15, c=60, num=1, ball=None):
    """
    初始化弹球程序的数据
    """
    if not ball:
        ball={}

    ball['row'] = r
    ball['col'] = c
    ball['canvas'] = createCanvas(r, c)
    ball['pause'] = False
    ball['num'] = num
    ball['balls'] = []

    for i in range(num):
        data = {}
        data['r'] = random.randint(1, 1)
        data['x'] = random.randint(1, ball['col'] - data['r'] - 1)
        data['y'] = random.randint(1, ball['row'] - data['r'] - 1)
        data['x_inc'] = random.choice([1, -1])
        data['y_inc'] = random.choice([1, -1])
        data['color'] = vt.getColor()
        data['ch'] = random.choice('@*&%+-SABCDEFGHI')

        ball['balls'].append(data)

    return ball


def ballProInit(row=15, col=60, num=1):
    """
    弹球程序的初始化操作
    """
    vt.run([vt.SCREEN, vt.HIDE])
    gt.init()
    return initBallDict(row, col, num)

def ballProExit(ball):
    """
    弹球程序退出终端还原操作
    """
    vt.run([vt.goto(ball['row'] + 2), vt.SHOW])
    gt.exit()
    os._exit(0)

def move(row, col, ball):
    """
    一个弹球运动控制
    ball:一个弹球的对象
    """
    if ball['x'] <= 0 or ball['x'] + ball['r'] > col - 1:
        ball['x_inc'] *= -1
        ball['color'] = vt.getColor()

    if ball['y'] <= 0 or ball['y'] + ball['r'] > row - 1:
        ball['y_inc'] *= -1
        ball['color'] = vt.getColor()

    ball['x'] += ball['x_inc']
    ball['y'] += ball['y_inc']

def moves(ball):
    """
    所有球的运动控制
    """
    for i in range(ball['num']):
        move(ball['row'], ball['col'], ball['balls'][i])

def ballRun():
    """
    弹球动画流程
    """
    if ball['pause']:
        return

    initCanvas(ball['canvas'], ball['row'], ball['col'])
    draws(ball)
    moves(ball)
    showCanvas(ball)

    #   下一次动画显示的延时设置
    gt.run(ballRun, 0.1)

def getInput(ball):
    """
    获取按键并且处理
    """
    while True:
        ch = gt.get()
        if ch == 'q' or ord(ch) == 27:
            break
        elif ch == ' ':
            ball['pause'] = not ball['pause']
            gt.run(ballRun)

if __name__ == '__main__':
    n = 10 if len(sys.argv) < 2 else int(sys.argv[1])
    ball = ballProInit(num=n)
    gt.run(ballRun)
    getInput(ball)
    ballProExit(ball)
